GtkCssChange previous_change);
GtkCssChange (* tree_get_change) (const GtkCssSelectorTree *tree,
const GtkCssMatcher *matcher);
+ void (* add_specificity) (const GtkCssSelector *selector,
+ guint *ids,
+ guint *classes,
+ guint *elements);
guint (* hash_one) (const GtkCssSelector *selector);
int (* compare_one) (const GtkCssSelector *a,
const GtkCssSelector *b);
- guint increase_id_specificity :1;
- guint increase_class_specificity :1;
- guint increase_element_specificity :1;
guint is_simple :1;
};
return previous_change;
}
+/* DEFAULTS */
+
+static void
+gtk_css_selector_default_add_specificity (const GtkCssSelector *selector,
+ guint *ids,
+ guint *classes,
+ guint *elements)
+{
+ /* no specificity changes */
+}
+
/* DESCENDANT */
static void
gtk_css_selector_descendant_tree_match,
gtk_css_selector_descendant_get_change,
gtk_css_selector_descendant_tree_get_change,
+ gtk_css_selector_default_add_specificity,
gtk_css_selector_descendant_hash_one,
gtk_css_selector_descendant_compare_one,
- FALSE, FALSE, FALSE, FALSE
+ FALSE
};
/* DESCENDANT FOR REGION */
gtk_css_selector_descendant_for_region_tree_match,
gtk_css_selector_descendant_for_region_get_change,
gtk_css_selector_descendant_for_region_tree_get_change,
+ gtk_css_selector_default_add_specificity,
gtk_css_selector_descendant_for_region_hash_one,
gtk_css_selector_descendant_for_region_compare_one,
- FALSE, FALSE, FALSE, FALSE
+ FALSE
};
/* CHILD */
gtk_css_selector_child_tree_match,
gtk_css_selector_child_get_change,
gtk_css_selector_child_tree_get_change,
+ gtk_css_selector_default_add_specificity,
gtk_css_selector_child_hash_one,
gtk_css_selector_child_compare_one,
- FALSE, FALSE, FALSE, FALSE
+ FALSE
};
/* SIBLING */
gtk_css_selector_sibling_tree_match,
gtk_css_selector_sibling_get_change,
gtk_css_selector_sibling_tree_get_change,
+ gtk_css_selector_default_add_specificity,
gtk_css_selector_sibling_hash_one,
gtk_css_selector_sibling_compare_one,
- FALSE, FALSE, FALSE, FALSE
+ FALSE
};
/* ADJACENT */
gtk_css_selector_adjacent_tree_match,
gtk_css_selector_adjacent_get_change,
gtk_css_selector_adjacent_tree_get_change,
+ gtk_css_selector_default_add_specificity,
gtk_css_selector_adjacent_hash_one,
gtk_css_selector_adjacent_compare_one,
- FALSE, FALSE, FALSE, FALSE
+ FALSE
};
/* SIMPLE SELECTOR DEFINE */
return previous_change | GTK_CSS_CHANGE_ ## c; \
} \
\
+static void \
+gtk_css_selector_ ## n ## _add_specificity (const GtkCssSelector *selector, \
+ guint *ids, \
+ guint *classes, \
+ guint *elements) \
+{ \
+ if (increase_id_specificity) \
+ (*ids)++; \
+ if (increase_class_specificity) \
+ (*classes)++; \
+ if (increase_element_specificity) \
+ (*elements)++; \
+} \
+\
static const GtkCssSelectorClass GTK_CSS_SELECTOR_ ## c = { \
G_STRINGIFY(n), \
gtk_css_selector_ ## n ## _print, \
gtk_css_selector_ ## n ## _tree_match, \
gtk_css_selector_ ## n ## _get_change, \
gtk_css_selector_ ## n ## _tree_get_change, \
+ gtk_css_selector_ ## n ## _add_specificity, \
hash_func, \
comp_func, \
- increase_id_specificity, increase_class_specificity, increase_element_specificity, \
TRUE \
};\
\
gtk_css_selector_not_ ## n ## _tree_match, \
gtk_css_selector_ ## n ## _get_change, \
gtk_css_selector_ ## n ## _tree_get_change, \
+ gtk_css_selector_ ## n ## _add_specificity, \
hash_func, \
comp_func, \
- increase_id_specificity, increase_class_specificity, increase_element_specificity, \
TRUE \
};
return previous_change | GTK_CSS_CHANGE_REGION;
}
+static guint
+count_bits (guint n)
+{
+ guint result = 0;
+
+ for (result = 0; n != 0; result++)
+ n &= n - 1;
+
+ return result;
+}
+
+static void
+gtk_css_selector_region_add_specificity (const GtkCssSelector *selector,
+ guint *ids,
+ guint *classes,
+ guint *elements)
+{
+ (*elements)++;
+
+ (*classes) += count_bits (selector->region.flags);
+}
+
static guint
gtk_css_selector_region_hash_one (const GtkCssSelector *a)
{
gtk_css_selector_region_tree_match,
gtk_css_selector_region_get_change,
gtk_css_selector_region_tree_get_change,
+ gtk_css_selector_region_add_specificity,
gtk_css_selector_region_hash_one,
gtk_css_selector_region_compare_one,
- FALSE, FALSE, TRUE, TRUE
+ TRUE
};
/* CLASS */
{
for (; selector; selector = gtk_css_selector_previous (selector))
{
- const GtkCssSelectorClass *klass = selector->class;
-
- if (klass->increase_id_specificity)
- (*ids)++;
- if (klass->increase_class_specificity)
- (*classes)++;
- if (klass->increase_element_specificity)
- (*elements)++;
+ selector->class->add_specificity (selector, ids, classes, elements);
}
}